package com.shenhaofeng.app.http;

import com.shenhaofeng.app.http.adapter.Adapter;
import com.shenhaofeng.app.http.request.Request;
import com.shenhaofeng.app.http.response.Response;
import com.shenhaofeng.app.http.type.Types;

import java.lang.reflect.Type;

import rx.Observable;


/**
 * Created by Administrator on 2016/10/12.
 */
public interface Call {

    Request request();


    /**
     * 立即调用请求,并阻塞,直到反应可以进行处理
     */
    Response execute() throws Exception;


    /**
     * 执行Request,并且将Response解析为Result对象,通过{@link Creator}设置的{@link Adapter}来执行转化,如果Creator没有设置默认的Adapter
     * ,无法正常转化,并且将会抛出一个异常提示
     *
     * @param type 转化的数据类型的对象,提供类型
     * @param <T>  转化的数据类型
     * @return {@link Request}
     */
    <T> Result<T> execute(Types<T> type);


    /**
     * 执行Request,并且将Response解析为Result对象,通过{@link Adapter}来执行数据解析
     *
     * @param type    转化的数据类型对象,提供类型
     * @param adapter 如果设置为null,将通过{@link Creator}设置的{@link Adapter}来执行转化,如果Creator没有设置默认的Adapter
     *                ,无法正常转化,并且将会抛出一个异常提示
     * @param <T>     转化的数据类型
     * @return {@link Request}
     */
    <T> Result<T> execute(Types<T> type, Adapter adapter);


    /**
     * 获取一个可订阅对象,通过订阅触发请求,开始请求服务器,请求完成后response会通过订阅对象传递
     *
     * @return 可订阅的数据源
     */
    Observable<Response> response();


    /**
     * 执行Request,并且将Response解析为Result对象,通过{@link Creator}设置的{@link Adapter}来执行转化,如果Creator没有设置默认的Adapter
     * ,无法正常转化,并且将会抛出一个异常提示
     *
     * @param type 转化的数据类型对象,提供类型
     * @param <T>  转化的数据类型
     * @return 可订阅对象
     */
    <T> Observable<Result<T>> result(Types<T> type);


    /**
     * 执行Request,并且将Response解析为Result对象,通过{@link Creator}设置的{@link Adapter}来执行转化,如果Creator没有设置默认的Adapter
     * ,无法正常转化,并且将会抛出一个异常提示
     *
     * @param type    转化的数据类型对象,提供类型
     * @param adapter 如果设置为null,将通过{@link Creator}设置的{@link Adapter}来执行转化,如果Creator没有设置默认的Adapter
     *                ,无法正常转化,并且将会抛出一个异常提示
     * @param <T>     转化的数据类型
     * @return
     */
    <T> Observable<Result<T>> result(Types<T> type, Adapter adapter);


    /**
     * 执行一个异步的的请求
     *
     * @throws IllegalStateException when the call has already been executed.
     */
    void enqueue(ResponseCallback responseResponseCallback);


    /**
     * 执行一个转化数据的异步请求,当服务器返回数据是,将会封装转换数据
     *
     * @param type           数据类型容器
     * @param adapter        转换器,如果设置为null,将通过{@link Creator}设置的{@link Adapter}来执行转化,如果Creator没有设置默认的Adapter
     *                       ,无法正常转化,并且将会抛出一个异常提示
     * @param resultCallback 回调接口
     * @param <T>            数据类型
     */
    <T> void enqueue(Types<T> type, Adapter adapter, ResultCallback resultCallback);


    /**
     * 执行一个转化数据的异步请求,当服务器返回数据是,将会封装转换数据
     * 将通过{@link Creator}设置的{@link Adapter}来执行转化,如果Creator没有设置默认的Adapter,无法正常转化,并且将会抛出一个异常提示
     *
     * @param type           数据类型容器
     * @param resultCallback 回调接口
     * @param <T>            数据类型
     */
    <T> void enqueue(Types<T> type, ResultCallback resultCallback);


    /**
     * 取消这个请求,如果已经完成，无法取消
     */
    void cancel();


    /**
     * 如果在{@linkplain #execute() executed} or {@linkplain
     * #enqueue(ResponseCallback) enqueued}. 值为true的情况下多次调用将会抛出异常
     */
    boolean isExecuted();


    /**
     * 是否已取消
     *
     * @return
     */
    boolean isCanceled();


    HttpClient httpClient();


    interface Factory {
        Call newCall(Request request);
    }


}
